/*
 * Copyright (c) 2002-2004, Inversoft, All Rights Reserved
 *
 * This software is distribuable under the GNU Lesser General Public License.
 * For more information visit gnu.org.
 */
package org.emergent.antbite.savant.ant.types;


import java.io.File;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.Cvs;
import org.apache.tools.ant.types.DataType;

import org.emergent.antbite.savant.Artifact;
import org.emergent.antbite.savant.LocalCacheStore;
import org.emergent.antbite.savant.Process;
import org.emergent.antbite.savant.SavantException;


/**
 * <p>
 * This class is a CVS process that attempts to locate
 * artifacts in a CVS module. This is done using the
 * CVS tasks.
 * </p>
 *
 * @author  Brian Pontarelli
 */
public class CVSProcess extends DataType implements Process {

    private String cvsroot;
    private boolean compression;
    private int compressionlevel;
    private String cvsrsh;
    private File dest;
    private String pack;
    private String tag;
    private String date;
    private int port;
    private File passfile;


    /**
     * Constructs a new <code>CVSProcess</code> with no repository or checkout
     * directory specified.
     */
    public CVSProcess() {
    }


    public void setCvsroot(String cvsroot) {
        this.cvsroot = cvsroot;
    }

    public void setCompression(boolean compression) {
        this.compression = compression;
    }

    public void setCompressionlevel(int compressionlevel) {
        this.compressionlevel = compressionlevel;
    }

    public void setCvsrsh(String cvsrsh) {
        this.cvsrsh = cvsrsh;
    }

    public void setDest(File dest) {
        this.dest = dest;
    }

    public void setPackage(String pack) {
        this.pack = pack;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setPassfile(File passfile) {
        this.passfile = passfile;
    }

    /**
     * <p>
     * This method attempts to locate the dependencies of the given Artifact
     * using the an XML dependency file fetched from the CVS repository.
     * If the dependency file exists, the given artifact is updated.
     * </p>
     *
     * @param   artifact The artifact to update with the resolved dependencies.
     * @return  True if the artifact was updated, false otherwise.
     * @throws  SavantException If the resolution failed or the XML was corrupt.
     */
    public boolean resolveArtifactDependencies(Artifact artifact,
            LocalCacheStore localCache)
    throws SavantException {
        File depsFile = executeCheckout(artifact.getArtifactDepsFile());
        if (depsFile.exists()) {
            localCache.storeDeps(artifact, depsFile);
            return true;
        }

        return false;
    }

    /**
     * Attempts to fetch the artifact given from a CVS repository. The name of
     * the repository is either specified in the XML as an attribute or can be
     * passed in during construction or set after construction. The location
     * to checkout the repository is also specified in the same manner.
     *
     * @param   artifact The artifact to look for
     * @param   localCache The local cache store to copy the artifact to after
     *          it is found
     * @return  The artifact or null if not found
     */
    public File fetch(Artifact artifact, LocalCacheStore localCache)
    throws SavantException {
        File artifactFile = executeCheckout(artifact.getArtifactFile());
        if (artifactFile.exists()) {
            artifactFile = localCache.store(artifact, artifactFile);
        } else {
            artifactFile = null;
        }

        return artifactFile;
    }

    protected File executeCheckout(String filePath) {
        // Set the default destination
        if (dest == null) {
            dest = new File(System.getProperty("user.home") + File.separator +
                ".savant_cvs_repository");
        }

        Cvs cvs = (Cvs) getProject().createTask("cvs");
        cvs.setPackage(pack);
        cvs.setCvsRoot(cvsroot);
        cvs.setCvsRsh(cvsrsh);
        cvs.setCompression(compression);
        cvs.setCompressionLevel(compressionlevel);
        cvs.setDest(dest);
        cvs.setTag(tag);
        cvs.setDate(date);
        cvs.setPort(port);
        cvs.setPassfile(passfile);
        cvs.setReallyquiet(true);

        // Check out the module from CVS
        String module = pack + File.separator + filePath;
        cvs.setPackage(module);
        cvs.perform();

        String file = pack + File.separator + filePath;
        return new File(dest, file);
    }

    /**
     * Validates that the caller supplied a package.
     *
     * @throws  BuildException If package is null
     */
    public void validate() throws BuildException {
        if (pack == null) {
            throw new BuildException("A package must be specified");
        }
    }
}
